#include "translate.h"

root_t varTable = RB_ROOT;
root_t arrayTable = RB_ROOT;

/*
DEBUG("%d\n",node->line);
DEBUG("%s\n",node->typename);
if(node->terminal == 1)
DEBUG("%s\n",node->val);
*/


argsList* newArgsList(operand t)
{
    argsList* ret = (argsList*)malloc(sizeof(argsList));
    ret->t = t;
    ret->next = NULL;
    return ret;
}

argsList* insertArgsList(argsList* args, argsList* newArg)
{
    if(!args) return newArg;
    else if(!newArg) return args;
    else{
        newArg->next = args;
        return newArg;
    }
}

void translateError(int tsErrType)
{
    fprintf(stderr, "Cannot translate: %s\n", tsErrMsg[tsErrType]);
    exit(1);
}

bool isNull(operand t)
{
    return t.type == EOPR;
}

static bool cmp(treenode* node, const char* str)
{
    if(!node) return false;
    return strcmp(node->typename, str) == 0;
}

bool cmpop(treenode* node, const char* op)
{
    if(!node) return false;
    return strcmp(node->val, op) == 0;
}

operand getVar(const char* name)
{
    map_t* target = get(&varTable, name);
    map_t* targetInArrayTable = get(&arrayTable, name);
    bool addr = 0;
    if(targetInArrayTable && ((arrayTs*)(targetInArrayTable->val))->para)
        addr = 1;
    if(!target)
    {
        int num = getVarNum();
        int *val = (int*)malloc(sizeof(int));
        *val = num;
        put(&varTable,name,val);
        operand opr = newOpr(VARIABLE, num);
        opr.addr = addr;
        return opr;
    }
    operand opr = newOpr(VARIABLE, *((int*)(target->val)));
    opr.addr = addr;
    return opr;
}

interCode* tsProgram(treenode* node)
{   /* Program: ExtDefList */
    return tsExtDefList(node->next[0]);
}

interCode* tsExtDefList(treenode* node)
{   /* ExtDefList: ExtDef ExtDefList
        | empty */
    if(node->capacity == 0) return NULL;
    interCode *code1 = tsExtDef(node->next[0]),
                *code2 = tsExtDefList(node->next[1]); 
    return mergeIC(code1, code2);
}

void tsSpecifier(treenode* node)
{   /* Specifier: TYPE
        | StructSpecifier */
    treenode* next0 = node->next[0];
    if(cmp(next0, "TYPE"))
    {
        if(strcmp(next0->val, "float") == 0)
            translateError(HAS_FLOAT);
    }
    else if(cmp(next0, "StructSpecifier"))
        translateError(HAS_STRUCTURE);
    else assert(0);
}

interCode* tsExtDef(treenode* node)
{   /* ExtDef: Specifier ExtDecList SEMI
        | Specifier SEMI
        | Specifier FunDec CompSt */
    treenode* next1 = node->next[1];
    if(cmp(next1, "ExtDecList"))
    {
        return NULL;
    }
    else if(cmp(next1, "SEMI"))
    {
        return NULL;
    }
    else if(cmp(next1, "FunDec"))
    {
        tsSpecifier(node->next[0]);
        interCode* ic1 = tsFunDec(next1);
        interCode* ic2 = tsCompSt(node->next[2]);
        return mergeIC(ic1,ic2);
    }
}

interCode* tsFunDec(treenode *node)
{   /* FunDec: ID LP VarList RP
        | ID LP RP */
    interCode* ic1 = newFunctionIC(node->next[0]->val);
    interCode* ic2 = NULL;
    if(node->capacity == 4)
    {
        ic2 = tsVarList(node->next[2]);//TODO
    }
    return mergeIC(ic1, ic2);
}

interCode* tsVarList(treenode* node)
{   /* VarList: ParamDec COMMA VarList
        | ParamDec */
    if(node->capacity == 1)
    {
        return tsParamDec(node->next[0]);
    }
    else if(node->capacity == 3)
    {
        interCode *code1 = tsParamDec(node->next[0]),
                    *code2 = tsVarList(node->next[2]);
        return mergeIC(code1, code2);
    }

}

interCode* tsParamDec(treenode* node)
{   /* ParamDec: Specifier VarDec */
    tsSpecifier(node->next[0]);
    return tsFuncVarDec(node->next[1]);
}

interCode* tsFuncVarDec(treenode* node)
{   /* VarDec: ID
        | VarDec LB INT RB */
    if(node->capacity == 1)
    {
        operand opr = getVar(node->next[0]->val);
        return newParamIC(opr);
    }
    else if(node->capacity == 4)
    {
        int dim = 0, sumSize = 0;
        treenode* itr = node;
        sizeLink *sl = NULL, *slTail = NULL;
        while(itr->capacity == 4)
        {
            dim++;
            int curSize = atoi(itr->next[2]->val);
            sizeLink* p = newSizeLink(curSize);
            sumSize += curSize;
            if(!sl) 
            {
                sl = p;
                slTail = sl;
            }
            else 
            {
                slTail->next = p;
                slTail = p;
            }
            itr = itr->next[0];
        }
        arrayTs* val = newArrayTs(dim, sl, 1);
        put(&arrayTable, itr->next[0]->val, val);
        operand opr = getVar(itr->next[0]->val);
        return newParamIC(opr);
    }
    else assert(0);
    return NULL;
}

interCode* tsCompSt(treenode* node)
{   /* CompSt: LC DefList StmtList RC */
    interCode* ic1 = tsDefList(node->next[1]);
    interCode* ic2 = tsStmtList(node->next[2]);
    return mergeIC(ic1, ic2);
}

interCode* tsDefList(treenode* node)
{   /* DefList: Def DefList
        | empty */
    if(node->capacity != 0)
    {
        interCode* ic1 = tsDef(node->next[0]);
        interCode* ic2 = tsDefList(node->next[1]);
        return mergeIC(ic1,ic2);
    }
    return NULL;
}

interCode* tsDef(treenode* node)
{   /* Def: Specifier DecList SEMI */
    tsSpecifier(node->next[0]);
    return tsDecList(node->next[1]);
}

interCode* tsDecList(treenode *node)
{   /* DecList: Dec
        | Dec COMMA DecList */
    interCode* ic1 = tsDec(node->next[0]);
    interCode* ic2 = NULL;
    if(node->capacity == 3)
    {
        ic2 = tsDecList(node->next[2]);
    }
    return mergeIC(ic1, ic2);
}

interCode* tsDec(treenode* node)
{   /* Dec: VarDec
        | VarDec ASSIGNOP Exp */
    if(node->capacity == 3)
    {
        return tsVarDec(node->next[0], node->next[2]);
    }
    else
        return tsVarDec(node->next[0], NULL);
}

interCode* tsVarDec(treenode* node, treenode* exp)
{   /* VarDec: ID
        | VarDec LB INT RB */
    if(node->capacity == 1)
    {
        if(exp)
        {
            operand opr = getVar(node->next[0]->val);
            return tsExp(exp, opr);
        }
    }
    else if(node->capacity == 4)
    {
        int dim = 0, sumSize = 1;
        treenode* itr = node;
        sizeLink *sl = NULL, *slTail = NULL;
        while(itr->capacity == 4)
        {
            dim++;
            int curSize = atoi(itr->next[2]->val);
            sizeLink* p = newSizeLink(curSize);
            sumSize *= curSize;
            if(!sl) 
            {
                sl = p;
                slTail = sl;
            }
            else 
            {
                slTail->next = p;
                slTail = p;
            }
            itr = itr->next[0];
        }
        arrayTs* val = newArrayTs(dim, sl, 0);
        put(&arrayTable, itr->next[0]->val, val);
        operand opr = getVar(itr->next[0]->val);
        interCode* ic1 = newDecIC(opr.varID, sumSize*4);
        if(exp)
        {interCode* ic2 = tsExp(exp, opr);
        ic1 = mergeIC(ic1, ic2);}
        return ic1;
    }
    else assert(0);
    return NULL;
}

operand tsArray(treenode* node, interCode** code1, interCode** code2, int *dimRecord, arrayTs **aa)
{
    treenode* itr = node;
    int dim = 0;
    while(itr->capacity == 4)
    {
        dim++;
        itr = itr->next[0];
    }
    *dimRecord = dim;
    operand arrayVar = getVar(itr->next[0]->val);
    *aa = (arrayTs*)(get(&arrayTable,itr->next[0]->val)->val);
    itr = node;
    operand preOpr = nullOpr;//t1: exp2 | t2: t1*size[dim] | t3: t2 + pre_t3 
    while(itr->capacity == 4)
    {   dim--;
        if(itr->next[2]->capacity == 1 && cmp(itr->next[2]->next[0], "INT") && atoi(itr->next[2]->next[0]->val) == 0)
        {
            itr = itr->next[0];
            continue;
        }   
        operand t1 = newOpr(TEMP,getTmpNum());
        *code2 = tsExp(itr->next[2],t1);
        *code1 = mergeIC(*code1, *code2);
        if((*aa)->size[dim] != 1)
        {
            operand t2 = newOpr(TEMP, getTmpNum());
            *code2 = newAssignIC(t2,t1,newOpr(CONSTANT,(*aa)->size[dim]),MUL);
            *code1 = mergeIC(*code1, *code2);
            if(preOpr.type != EOPR)
            {
                operand t3 = newOpr(TEMP, getTmpNum());
                *code2 = newAssignIC(t3,t2,preOpr,ADD);
                *code1 = mergeIC(*code1, *code2);
                preOpr = t3;
            }
            else
                preOpr = t2;
        }
        else
        {
            preOpr = t1;
        }
        itr = itr->next[0];
    }
    operand resPos = arrayVar;
    if(preOpr.type != EOPR)
    {    
        operand offset = newOpr(TEMP, getTmpNum());
        *code2 = newAssignIC(offset, preOpr, newOpr(CONSTANT, 4),MUL);
        *code1 = mergeIC(*code1,*code2);
        resPos = newOpr(TEMP, getTmpNum());
        if(arrayVar.addr == 0)
            *code2 = newAssignIC(resPos, arrayVar, offset, ADDR);
        else
            *code2 = newAssignIC(resPos, arrayVar, offset, ADD);
        *code1 = mergeIC(*code1, *code2);
    }
    else
    {
        if(arrayVar.addr == 0)
        {
            resPos = newOpr(TEMP, getTmpNum());
            *code2 = newAssignIC(resPos, arrayVar, nullOpr, ADDR);
            *code1 = mergeIC(*code1, *code2);
        }
    }
    return resPos;
}

interCode* tsExp(treenode* node, operand place)
{   /* Exp: Exp < ASSIGNOP AND OR RELOP PLUS MINUS STAR DIV > Exp
        | LP Exp RP
        | MINUS Exp
        | NOT Exp
        | ID LP Args RP
        | ID LP RP
        | Exp LB Exp RB
        | Exp DOT ID
        | ID
        | INT
        | FLOAT */
    interCode* code1 = NULL;
    interCode* code2 = NULL;
    if(cmp(node->next[0], "Exp"))
    {
        if(node->capacity == 3)
        {
            if(cmp(node->next[2], "Exp"))
            {
                treenode *exp1 = node->next[0], *exp2 = node->next[2];
                if(cmp(node->next[1], "ASSIGNOP"))
                {
                    if(exp1->capacity == 1) // variable access
                    {
                        assert(cmp(exp1->next[0], "ID"));
                        operand opr = getVar(exp1->next[0]->val);
                        operand t1 = newOpr(TEMP, getTmpNum());
                        code2 = tsExp(exp2,t1);
                        code1 = mergeIC(code1, code2);
                        code2 = newAssignIC(opr,t1,nullOpr,AS);
                        code1 = mergeIC(code1, code2);
                        if(!isNull(place))
                        {code2 = newAssignIC(place,opr,nullOpr,AS);
                        code1 = mergeIC(code1, code2);}
                    }
                    else if(exp1->capacity == 4 && cmp(exp1->next[1], "LB"))// array access
                    {
                        operand t1 = newOpr(TEMP, getTmpNum());
                        code2 = tsExp(exp2, t1);
                        code1 = mergeIC(code1,code2);
                        int dimRecord = 0;
                        arrayTs* aa = NULL;
                        operand resPos = tsArray(exp1,&code1,&code2,&dimRecord,&aa);
                        if(dimRecord == aa->dim)
                        {
                            code2 = newAssignIC(resPos, t1, nullOpr, LSTAR);
                            code1 = mergeIC(code1,code2);
                            if(!isNull(place))
                            {code2 = newAssignIC(place, resPos, nullOpr, RSTAR);
                            mergeIC(code1,code2);}
                        }
                        else if(dimRecord < aa->dim)
                        {
                            translateError(POINTER_ASSIGNMENT);
                            /*code2 = newAssignIC(resPos,t1,nullOpr,AS);
                            code1 = mergeIC(code1,code2);
                            if(!isNull(place))
                            {code2 = newAssignIC(place,resPos, nullOpr, AS);
                            mergeIC(code1,code2);}*/
                        }
                        else assert(0);
                    }
                    else translateError(HAS_STRUCTURE);//structure
                }
                else if(cmp(node->next[1], "PLUS") || cmp(node->next[1], "MINUS") || cmp(node->next[1], "STAR") || cmp(node->next[1], "DIV"))
                {
                    if(isNull(place)) return NULL;
                    operand t1 = newOpr(TEMP, getTmpNum()),
                            t2 = newOpr(TEMP, getTmpNum());
                    code2 = tsExp(node->next[0],t1);
                    code1 = mergeIC(code1,code2);
                    code2 = tsExp(node->next[2], t2);
                    code1 = mergeIC(code1,code2);
                    int ch;
                    if(cmp(node->next[1], "PLUS")) ch = ADD;
                    else if(cmp(node->next[1], "MINUS")) ch = SUB;
                    else if(cmp(node->next[1], "STAR")) ch = MUL;
                    else if(cmp(node->next[1], "DIV")) ch = DIV;
                    code2 = newAssignIC(place,t1,t2,ch);
                    code1 = mergeIC(code1,code2);
                }
                else if(cmp(node->next[1], "RELOP") || cmp(node->next[1], "AND") || cmp(node->next[1], "OR"))
                {
                    if(isNull(place)) return NULL;
                    int label1 = getLabelNum(), label2 = getLabelNum();
                    code2 = newAssignIC(place, zeroOpr, nullOpr, AS);
                    code1 = mergeIC(code1, code2);
                    code2 = tsCond(node, label1, label2);
                    code1 = mergeIC(code1,code2);
                    code2 = newLabelIC(label1);
                    code1 = mergeIC(code1,code2);
                    code2 = newAssignIC(place,oneOpr,nullOpr,AS);
                    code1 = mergeIC(code1,code2);
                    code2 = newLabelIC(label2);
                    code1 = mergeIC(code1, code2);
                }
            }
            else translateError(HAS_STRUCTURE);//Exp: Exp DOT ID
        }
        else if(node->capacity == 4)// Exp: Exp LB Exp RB
        {
            if(isNull(place)) return NULL;
            int dimRecord = 0;
            arrayTs* aa = NULL;
            operand resPos = tsArray(node,&code1,&code2,&dimRecord,&aa);
            if(dimRecord == aa->dim)
            {
                code2 = newAssignIC(place, resPos, nullOpr, RSTAR);
            }
            else if(dimRecord < aa->dim)
            {
                translateError(POINTER_ASSIGNMENT);
                //code2 = newAssignIC(place,resPos, nullOpr, AS);
            }
            else assert(0);
            code1 = mergeIC(code1,code2);
        }
    }
    else if(cmp(node->next[0], "INT") && node->capacity == 1) // Exp: INT
    {
        if(isNull(place)) return NULL;
        int value = atoi(node->next[0]->val);
        return newAssignIC(place, newOpr(CONSTANT, value), nullOpr, AS);
    }
    else if(cmp(node->next[0], "ID") && node->capacity == 1) // Exp: ID
    {
        if(isNull(place)) return NULL;
        operand opr = getVar(node->next[0]->val);
        map_t* target = get(&arrayTable, node->next[0]->val); 
        if(target && opr.addr == 0)//func(arrayName) array is not para
            return newAssignIC(place, opr, nullOpr, ADDR);
        else
            return newAssignIC(place, opr, nullOpr, AS);
    }
    else if(cmp(node->next[0], "FLOAT")) translateError(HAS_FLOAT);
    else if(cmp(node->next[0], "MINUS")) // Exp: MINUS Exp
    {
        if(isNull(place)) return NULL;
        if(node->next[1]->capacity == 1 && cmp(node->next[1]->next[0], "INT"))
        {
            operand cons = newOpr(CONSTANT, -atoi(node->next[1]->next[0]->val));
            code1 = newAssignIC(place,cons,nullOpr,AS);
            return code1;
        }
        operand t1 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node->next[1],t1);
        code2 = newAssignIC(place, zeroOpr, t1, SUB);
        return mergeIC(code1,code2);
    }
    else if(cmp(node->next[0], "NOT"))
    {
        if(isNull(place)) return NULL;
        int label1 = getLabelNum(), label2 = getLabelNum();
        code2 = newAssignIC(place, zeroOpr, nullOpr, AS);
        code1 = mergeIC(code1, code2);
        code2 = tsCond(node, label1, label2);
        code1 = mergeIC(code1,code2);
        code2 = newLabelIC(label1);
        code1 = mergeIC(code1,code2);
        code2 = newAssignIC(place,oneOpr,nullOpr,AS);
        code1 = mergeIC(code1,code2);
        code2 = newLabelIC(label2);
        code1 = mergeIC(code1, code2);
        return code1;
    }
    else if((node->capacity == 3 || node->capacity == 4) && cmp(node->next[0], "ID"))// Exp: ID LP RP | ID LP Args RP
    {
        char buffer[32];
        strcpy(buffer, node->next[0]->val);
        if(isNull(place) && strcmp(buffer, "read") != 0 && strcmp(buffer, "write") != 0)
            place = newOpr(TEMP, getTmpNum());
        if(node->capacity == 3)
        {
            if(strcmp(buffer, "read") == 0 && !isNull(place))
                return newReadIC(place);
            return newCallIC(place, buffer);
        }
        else if(node->capacity == 4)
        {
            argsList* args = NULL;
            code1 = tsArgs(node->next[2], &args);
            if(strcmp(buffer, "write") == 0)
            {
                code1 = mergeIC(code1, newWriteIC(args->t));
                if(!isNull(place))
                    code1 = mergeIC(code1, newAssignIC(place, zeroOpr, nullOpr, AS));
                return code1;
            }
            else{
                argsList* tmp = args;
                while(tmp)
                {
                    code2 = mergeIC(code2, newArgIC(tmp->t));
                    tmp = tmp->next;
                }
                code1 = mergeIC(code1, code2);
                code1 = mergeIC(code1, newCallIC(place, buffer));
                return code1;
            }
        }
    }
    else if(node->capacity == 3 && (node->next[0], "LP"))
    {
        return tsExp(node->next[1],place);
    }
    else assert(0);
    return code1;

}

interCode* tsArgs(treenode* node, argsList** args)
{   /* Args: Exp COMMA Args
        | Exp */
    interCode *code1 = NULL, *code2 = NULL;

    if(node->capacity == 1)//Args: Exp
    {
        operand t1 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node->next[0], t1);
        argsList* newArg = newArgsList(t1);
        *args = insertArgsList(*args, newArg);
        return code1;
    }
    else if(node->capacity == 3)
    {
        operand t1 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node->next[0],t1);
        argsList* newArg = newArgsList(t1);
        *args = insertArgsList(*args, newArg);
        code2 = tsArgs(node->next[2], args);
        return mergeIC(code1, code2);
    }
    else assert(0);
}

interCode* tsCond(treenode* node, int labelt, int labelf)
{
    interCode *code1 = NULL, *code2 = NULL;
    if(node->capacity == 3 && cmp(node->next[1], "RELOP"))// Exp RELOP Exp
    {
        operand t1 = newOpr(TEMP, getTmpNum()),
                t2 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node->next[0], t1);
        code2 = tsExp(node->next[2], t2);
        code1 = mergeIC(code1, code2);
        int op;
        treenode* opNode = node->next[1];
        if(cmpop(opNode, "==")) op = EQ;
        else if(cmpop(opNode, "!=")) op = NE;
        else if(cmpop(opNode, "<=")) op = LE;
        else if(cmpop(opNode, "<")) op = LT;
        else if(cmpop(opNode, ">=")) op = GE;
        else if(cmpop(opNode, ">")) op = GT;
        code2 = newCondIC(t1, t2, op, labelt);
        code1 = mergeIC(code1, code2);
        code2 = newGotoIC(labelf);
        code1 = mergeIC(code1, code2);
        return code1;
    }
    else if(node->capacity == 3 && cmp(node->next[1], "AND"))// Exp AND Exp
    {
        int label1 = getLabelNum();
        code1 = tsCond(node->next[0], label1, labelf);
        code2 = newLabelIC(label1);
        code1 = mergeIC(code1, code2);
        code2 = tsCond(node->next[2], labelt, labelf);
        code1 = mergeIC(code1, code2);
        return code1;
    }
    else if(node->capacity == 3 && cmp(node->next[1], "OR"))// Exp OR Exp
    {
        int label1 = getLabelNum();
        code1 = tsCond(node->next[0], labelt, label1);
        code2 = newLabelIC(label1);
        code1 = mergeIC(code1, code2);
        code2 = tsCond(node->next[2], labelt, labelf);
        code1 = mergeIC(code1, code2);
        return code1;
    }
    else if(node->capacity == 2 && cmp(node->next[0], "NOT"))// NOT Exp
    {
        return tsCond(node->next[1],labelf,labelt);
    }
    else
    {
        operand t1 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node,t1);
        code2 = newCondIC(t1, zeroOpr,NE,labelt);
        code1 = mergeIC(code1, code2);
        code2 = newGotoIC(labelf);
        code1 = mergeIC(code1,code2);
        return code1;
    }
}

interCode* tsStmtList(treenode* node)
{   /* StmtList: Stmt StmtList
        | empty */
    if(node->capacity == 2) // StmtList: Stmt StmtList
    {
        interCode *code1 = tsStmt(node->next[0]),
                    *code2 = tsStmtList(node->next[1]);
        return mergeIC(code1,code2);
    }
    else // StmtList: empty
        return NULL;
}

interCode* tsStmt(treenode* node)
{   /* Stmt: Exp SEMI
        | CompSt
        | RETURN Exp SEMI
        | IF LP Exp RP Stmt
        | IF LP Exp RP Stmt ELSE Stmt
        | WHILE Lp Exp RP Stmt */
    interCode *code1 = NULL, *code2 = NULL;
    if(node->capacity == 2 && cmp(node->next[0], "Exp"))
    {
        return tsExp(node->next[0],nullOpr);
    }
    else if(node->capacity == 1 && cmp(node->next[0], "CompSt"))
    {
        return tsCompSt(node->next[0]);
    }
    else if(node->capacity == 3 && cmp(node->next[0], "RETURN"))
    {
        operand t1 = newOpr(TEMP, getTmpNum());
        code1 = tsExp(node->next[1], t1);
        code2 = newReturnIC(t1);
        return mergeIC(code1, code2);
    }
    else if(cmp(node->next[0], "IF"))
    {
        if(node->capacity == 5)// IF LP Exp RP Stmt
        {
            int label1 = getLabelNum(), label2 = getLabelNum();
            code1 = tsCond(node->next[2],label1, label2);
            code2 = tsStmt(node->next[4]);
            code1 = mergeIC(code1, newLabelIC(label1));
            code2 = mergeIC(code2, newLabelIC(label2));
            return mergeIC(code1, code2);
        }
        else if(node->capacity == 7)// IF LP Exp RP Stmt ELSE Stmt
        {
            int label1 = getLabelNum(), label2 = getLabelNum(), label3 = getLabelNum();
            interCode* code3 = NULL;
            code1 = tsCond(node->next[2], label1, label2);
            code2 = tsStmt(node->next[4]);
            code3 = tsStmt(node->next[6]);
            code1 = mergeIC(code1, newLabelIC(label1));
            code1 = mergeIC(code1, code2);
            code1 = mergeIC(code1, newGotoIC(label3));
            code1 = mergeIC(code1, newLabelIC(label2));
            code1 = mergeIC(code1,code3);
            return mergeIC(code1, newLabelIC(label3));
        }
        else assert(0);
    }
    else if(node->capacity == 5 && cmp(node->next[0], "WHILE"))
    {
        int label1 = getLabelNum(), label2 = getLabelNum(), label3 = getLabelNum();
        code1 = tsCond(node->next[2], label2, label3);
        code2 = tsStmt(node->next[4]);
        code1 = mergeIC(newLabelIC(label1), code1);
        code1 = mergeIC(code1, newLabelIC(label2));
        code1 = mergeIC(code1, code2);
        code1 = mergeIC(code1, newGotoIC(label1));
        return mergeIC(code1, newLabelIC(label3));
    }
    else assert(0);
}

void translate(FILE* fp, treenode* node)
{
    interCode* code = tsProgram(node);
    interCodeToFile(code,fp);
    freeMap(&varTable,free);
    freeMap(&arrayTable, freeArrayTs);
    /*interCode *head = code->prev, *cur = code, *next = code->next;
    while(cur != head)
    {
        free(cur);
        cur = next;
        next = cur->next;
    }*/
}

interCode* getTsCode(treenode* node)
{
    interCode* code = tsProgram(node);
    //printIC(code);
    return code;
}